﻿using Commons.Collections;
using NVelocity;
using NVelocity.App;
using NVelocity.Context;
using NVelocity.Runtime;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;

///模板引擎辅助，有两个类，分别是参考老杨和小泥鳅的类。
namespace DreamCMS.WebCore.Common
{
    /// <summary>
    /// 模板引擎辅助类（参考老杨的做法）。
    /// 这个类可以是静态的，因为其context模板上下文对象是局部变量，调用方法的时候每个用户会独立拥有一份拷贝。
    /// </summary>
    public class TplEngine
    {
        /// <summary>
        /// 用data数据填充templateName模板，渲染生成html返回
        /// </summary>
        /// <param name="templateName">模板文件路径</param>
        /// <param name="data">数据对象</param>
        /// <returns></returns>
        public static void RenderHtml(string templatePath, object data)
        {
            //根据templatePath获取模板路径和模板文件名
            string tplDir = templatePath.Substring(0, templatePath.LastIndexOf('/'));
            string tplName = templatePath.Substring(templatePath.LastIndexOf('/'));
            //创建模板引擎（VelocityEngine）并设置属性
            VelocityEngine vltEngine = new VelocityEngine();
            vltEngine.SetProperty(RuntimeConstants.RESOURCE_LOADER, "file");
            vltEngine.SetProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, System.Web.Hosting.HostingEnvironment.MapPath("~/" + tplDir));//模板文件所在的文件夹
            vltEngine.AddProperty(RuntimeConstants.INPUT_ENCODING, "utf-8");          // 输入编码格式设置
            vltEngine.AddProperty(RuntimeConstants.OUTPUT_ENCODING, "utf-8");         // 输出编码格式设置
            vltEngine.Init();
            // 2.Velocity 上下文对象设置
            VelocityContext vltContext = new VelocityContext();
            vltContext.Put("data", data);//设置页面参数来完善Velocity上下文对象，在模板中可以通过$data来引用。
            vltContext.Put("tplDir", tplDir); //模板中通过$tplDir获取模板路径来引入css等文件

            //得到html模板文件
            Template vltTemplate = vltEngine.GetTemplate(tplName);

            /*
            //准备一个StringWriter字符串缓冲区
            System.IO.StringWriter vltWriter = new System.IO.StringWriter();
            vltTemplate.Merge(vltContext, vltWriter);//把模板和上下文对象进行融合。
            */


            //我们这里直接将模板和上下文对象融合返回到输出流中
            vltTemplate.Merge(vltContext, HttpContext.Current.Response.Output);
            // HttpContext.Current.Response.End(); 如果想让Response输出流到此结束不再输出则End即可。
            //string html = vltWriter.GetStringBuilder().ToString();  暂时不用这一句了
        }

    }


    /// <summary>
    /// 模板封装类(参考的别人的)
    /// 这里不能用静态类，因为类中的模板引擎数据是基于用户实例的，不同的用户在实例化
    /// 如果用静态方法访问静态成员的话，静态成员是所有用户共用的，肯定会出问题。
    /// </summary>
    public class TemplateHelper
    {
        private VelocityEngine velocity = null;
        private IContext context = null;

        public TemplateHelper(string templatePath)
        {
            velocity = new VelocityEngine();

            //使用设置初始化VelocityEngine
            ExtendedProperties props = new ExtendedProperties();

            props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, templatePath);
            props.AddProperty(RuntimeConstants.INPUT_ENCODING, "utf-8");

            //   props.AddProperty(RuntimeConstants.OUTPUT_ENCODING, "gb2312");
            //    props.AddProperty(RuntimeConstants.RESOURCE_LOADER, "file");

            //  props.SetProperty(RuntimeConstants.RESOURCE_MANAGER_CLASS, "NVelocity.Runtime.Resource.ResourceManagerImpl\\,NVelocity");

            velocity.Init(props);
            //RuntimeConstants.RESOURCE_MANAGER_CLASS 
            //为模板变量赋值
            context = new VelocityContext();

        }

        /// <summary>
        /// 给模板变量赋值
        /// </summary>
        /// <param name="key">模板变量</param>
        /// <param name="value">模板变量值</param>
        public void Put(string key, object value)
        {
            //if (context == null)
            //    context = new VelocityContext();
            if(value!=null)
            {
                context.Put(key, value);
            }
        }




        /// <summary>
        /// 生成字符
        /// </summary>
        /// <param name="templatFileName">模板文件名</param>
        public string BuildString(string templateFile)
        {
            //从文件中读取模板
            Template template = velocity.GetTemplate(templateFile);

            //合并模板(我给他加上了using，因为他实现了IDisposiable接口)
            using (StringWriter writer = new StringWriter())
            {
                template.Merge(context, writer);
                return writer.ToString();
            }
        }
    }
}